#include <iostream>
#include "bga/system/NodeListener.h"
//#include "bga/system/NodeEvent.h"

namespace bga
{

template< typename T >
Node<T>::Node(Node* parent) : parent(parent), element(NULL)
{
}

template< typename T >
Node<T>::~Node()
{
}

template< typename T >
Node<T>* Node<T>::createNode()
{
    return new Node<T>();
}

template< typename T >
void Node<T>::destroyNode(Node<T>* node)
{
    if(node != NULL)
    {
        delete node;
        node = NULL;
    }
}

template< typename T >
void Node<T>::addChild(Node<T>* node)
{
    /*if(!this->leftNode)
    {
        node->parent = this;
        this->leftNode.reset(node);
    }
    else
    {
        Node<T>* childNode = this->leftNode.get();
        while(childNode->rightNode.get() != NULL)
        {
            childNode = childNode->rightNode.get();
        }
        /// When exit, we are on the last brother, so we add the new node on right
        node->parent = childNode;
        childNode->rightNode.reset(node);
    }*/
    Scoped_Ptr<Node <T> > ptr;
    node->parent = this;
    /// We use insert to push back the element and get the iterator on its position
    typename std::list< Scoped_Ptr< Node<T> > >::iterator it = this->childrenList.insert(this->childrenList.end(), ptr);
    it->reset(node);

    node->handleNodeAddedEvent();
}

template< typename T >
T* Node<T>::getElement() const
{
    return this->element;
}

template< typename T >
void Node<T>::setElement(T& element)
{
    this->element = &element;
}

template< typename T >
Node<T>* Node<T>::getParent() const
{
    return this->parent;
}

template< typename T >
void Node<T>::addNodeListener(bga::NodeListener& nodeListener, bool herits)
{
    this->nodeListeners.push_back(&nodeListener);
    if(herits)
    {
        /*if(leftNode.get() != NULL)
        {
            leftNode->addNodeListener(nodeListener, herits);
        }

        if(rightNode.get() != NULL)
        {
            rightNode->addNodeListener(nodeListener, herits);
        }*/
        /*typename Scoped_Ptr< Node<T> >::iterator it;
        for(it != this->childrenList.begin(); it != this->childrenList.end(); ++it)
        {
            it->addNodeListener(nodeListener, herits);
        }*/
    }
}

template< typename T >
void Node<T>::handleNodeAddedEvent()
{
    NodeEvent event(*this);

    typename std::list< bga::NodeListener* >::iterator i;

    for(i = nodeListeners.begin(); i != nodeListeners.end(); ++i)
    {
        (*i)->nodeAdded(event);
    }
}

template< typename T >
void Node<T>::handleNodeRemovedEvent()
{
    NodeEvent event(*this);

    typename std::list< bga::NodeListener* >::iterator i;

    for(i = nodeListeners.begin(); i != nodeListeners.end(); ++i)
    {
        (*i)->nodeRemoved(event);
    }
}

template< typename T >
void Node<T>::handleNodeModifiedEvent()
{
    NodeEvent event(*this);

    typename std::list< bga::NodeListener* >::iterator i;

    for(i = nodeListeners.begin(); i != nodeListeners.end(); ++i)
    {
        (*i)->nodeModified(event);
    }
}

template< typename T >
void Node<T>::handleNodeProcessedEvent()
{
    NodeEvent event(*this);

    typename std::list< bga::NodeListener* >::iterator i;

    for(i = nodeListeners.begin(); i != nodeListeners.end(); ++i)
    {
        (*i)->nodeProcessed(event);
    }
}

}
